package com.example.demo.config.shiro;

import com.example.demo.config.shiro.AdminUserToken;
import com.example.demo.config.shiro.CommonUserToken;
import com.example.demo.entity.Admin;
import com.example.demo.entity.Person;
import com.example.demo.entity.User;
import com.example.demo.service.AdminService;
import com.example.demo.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * @Author: yucsa
 * @Date: 2021/8/20 13:29
 * Shiro的realm组件，配合ShiroConfig使用—— 后期为实现添加redis缓存，该类已不再使用
 * 为了配合多种用户角色登录，使用两个UsernamePasswordToken的子类，
 * 通过判断token的类型确定是普通用户还是管理员
 */
public class UserRealm extends AuthorizingRealm{

    @Autowired
    UserService userService;
    @Autowired
    AdminService adminService;
    //授权
    @Override
    /**
     * @yucs 2021/9/2
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){
        System.out.println("=====执行了授权=====");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Subject subject = SecurityUtils.getSubject();
        Person loginPerson = (Person)subject.getPrincipal();
        //如果登录角色是管理员
        /**
         * @yucs 2021/8/31 用addRole的方式授权
         */

        info.addRole("user");
        if(loginPerson.getRole()== 1){
            info.addRole("admin");
            System.out.println("给管理员授权了");
        }else if(loginPerson.getRole() == 0) {
            System.out.println("用户已授权");
        }else{
            System.out.println("UserRealm授权出错！");
            System.out.println(loginPerson.getRole());
        }
        return info;
    }

    //认证，这里分两个分支，分别取用户表和管理员表查询
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("=======执行了认证逻辑========");
        //普通用户的认证逻辑
        if(authenticationToken instanceof CommonUserToken){
            UsernamePasswordToken inputToken = (UsernamePasswordToken)authenticationToken;
            User loginUser = userService.findByName(inputToken.getUsername());
            if(loginUser == null){
                //return null会自动抛出未知用户名异常
                return null;
            }
            //密码认证
            return new SimpleAuthenticationInfo(loginUser,loginUser.getPassword(),"");
        }else if(authenticationToken instanceof AdminUserToken){
            UsernamePasswordToken inputToken = (UsernamePasswordToken)authenticationToken;
            Admin loginAdmin = adminService.queryAdminByName(inputToken.getUsername());
            if(loginAdmin == null){
                //return null会自动抛出未知用户名异常
                return null;
            }
            //密码认证
            return new SimpleAuthenticationInfo(loginAdmin,loginAdmin.getPassword(),"");
        }else{
            //既不是admin 又不是user
            return null;
        }

    }
}
